#ifndef REDIS_ADAPTOR_H
#define REDIS_ADAPTOR_H

#include <muduo/net/EventLoop.h>
#include <muduo/net/Channel.h>
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost;
using namespace muduo::net;


class RedisAdaptorMuduo : public boost::noncopyable
{
public:
	RedisAdaptorMuduo(const char *ip, int port, EventLoop *loop):
	loop_(loop)
	{
		ac = redisAsyncConnect(ip, port);
		if( ac != NULL )
		{
			return REDIS_ERR;
		}
		shared_ptr<Channel> channel(new Channel(loop, ac->fd));

		channel->setReadCallback(readCallback);
		channel->setWriteCallback(writeCallback);

		channel = channel;

		attachToHiredis(loop, ac);

		loop->updateChannel(*channel);

	}
	~RedisAdaptorMuduo()
	{
	}

	void attachToHiredis(EventLoop* loop, redisAsyncContext* c)
	{
		c->ev.addRead = enableRead;
		c->ev.delRead = disableRead;
		c->ev.addWrite = enableWrite;
		c->ev.delWrite = disableWrite;
		c->ev.cleanup = disabelAll;

		c->ev.data = NULL;
	}

	int handleRead( muduo::Timestamp timestamp)
	{
		redisAsyncHandleRead(context_);
	}

	void handleWrite()
	{
		redisAsyncHandleWrite(context_);
	}

	void enableRead(void *privdata)
	{
		channel_->enableReading();
	}

	void disableRead(void *privdate)
	{
		
	}

	void enableWrite(void *privdate)
	{
		channel_->enableWriting();
	}

	void disableWrite(void *privdate)
	{
		channel_->disableWriting();
	}

	void disabelAll(void *privdate)
	{
		channel_->disabelAll();
	}
	/* data */
private:
	EventLoop* loop_;
	shared_ptr<Channel> channel_;
	redisAsyncContext* ac_;
};

#endif